/*
rp2040默认I2C引脚是6-7,需要修改才能使用加速度传感器。
修改I2C默认引脚的方法 ：pins_arduino.h
 ~/.platformio/packages/framework-arduino-mbed/variants/RASPBERRY_PI_PICO/pins_arduino.h
 ~~~~~汤半泛
*/


#ifndef DISPLAY_H
#define DISPLAY_H

#include "Arduino.h"
#include "lvgl/lvgl.h"
#include "OneButton.h"
#include <TFT_eSPI.h>
#include <SPI.h>
#include "watch_face/WatchController.h"
#include "Bubble/BubbleController.h"
WatchController watchcontroller;
BubbleController bubblecontroller;

#define LV_HOR_RES 240 // must be change into what you want not the default setting of the screen.
#define LV_VER_RES 240

bool ENTER_BUTTON = false;
bool PREV_BUTTON = false;
bool NEXT_BUTTON = false;

OneButton enterButton(8, true);
OneButton prevButtton(7, true);
OneButton nextButton(9, true);

static uint8_t currentScreen = 2;

TFT_eSPI tft = TFT_eSPI();
;
// Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
void my_print(lv_log_level_t level, const char *file, uint32_t line, const char *fun, const char *dsc)
{
  char bf[50];
  sprintf(bf, "%s@%d %s->%s", file, line, fun, dsc);
  Serial.println(bf);
}

/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
  uint32_t w = (area->x2 - area->x1 + 1);
  uint32_t h = (area->y2 - area->y1 + 1);

  tft.startWrite();
  tft.setAddrWindow(area->x1, area->y1, w, h);
  tft.pushColors((uint16_t *)&color_p->full, w * h, true);
  tft.endWrite();

  lv_disp_flush_ready(disp_drv);
}

static void lv_encoder_read(lv_indev_drv_t *indev_drv, lv_indev_data_t *data)
{

  data->state = LV_INDEV_STATE_RELEASED;
  if (ENTER_BUTTON)
  {
    data->state = LV_INDEV_STATE_PR;
    ENTER_BUTTON = false;
  }
  else if (PREV_BUTTON)
  {
    data->enc_diff = -1;
    PREV_BUTTON = false;
  }
  else if (NEXT_BUTTON)
  {
    data->enc_diff = 1;
    NEXT_BUTTON = false;
  }
}
lv_timer_t *button_read_timer;
// lv_timer_t * button_read_timer = lv_timer_create([](lv_timer_t *timer){
//   enterButton.tick();
//   nextButton.tick();
//   prevButtton.tick();
// },10,NULL);

void lvglinit()
{

  lv_init();

  // // OR use this initializer (uncomment) if using a 1.14" 240x135 TFT:
  tft.init(); // Init ST7789 240x135
  // tft.setRotation(2);
  // tft.setSPISpeed(40000000);
  Serial.println(F("Initialized"));
  tft.setRotation(2);

  static lv_disp_draw_buf_t draw_buf;
  const size_t DISP_BUF_SIZE = sizeof(lv_color_t) * (LV_HOR_RES * 10); // best operation.
  // lv_color_t buf[DISP_BUF_SIZE];
  static lv_color_t buf1[DISP_BUF_SIZE];
  static lv_color_t buf2[DISP_BUF_SIZE];
  lv_disp_draw_buf_init(&draw_buf, buf1, buf2, DISP_BUF_SIZE); /*Initialize the display buffer*/

  /*-----------------------------------
   * Register the display in LVGL
   *----------------------------------*/

  static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/
  lv_disp_drv_init(&disp_drv);   /*Basic initialization*/

  /*Set up the functions to access to your display*/
  /*Set the resolution of the display*/
  disp_drv.hor_res = LV_HOR_RES;
  disp_drv.ver_res = LV_VER_RES;
  /*Used to copy the buffer's content to the display*/
  disp_drv.flush_cb = my_disp_flush;
  /*Set a display buffer*/
  disp_drv.draw_buf = &draw_buf;
  // disp_drv.full_refresh = 1;

  /*Finally register the driver*/
  lv_disp_drv_register(&disp_drv);

  enterButton.attachClick([]()
                          { ENTER_BUTTON = true; });
  prevButtton.attachClick([]()
                          { PREV_BUTTON = true; });
  nextButton.attachClick([]()
                         { NEXT_BUTTON = true; });
  static lv_indev_drv_t indev_drv;
  lv_indev_drv_init(&indev_drv);
  indev_drv.type = LV_INDEV_TYPE_ENCODER;
  indev_drv.read_cb = lv_encoder_read;
  // indev_drv.read_timer = button_read_timer;
  // indev_drv.user_data = lv_input_event;
  static lv_indev_t *lv_encoder_indev = lv_indev_drv_register(&indev_drv);
  lv_group_t *g = lv_group_create();
  lv_indev_set_group(lv_encoder_indev, g);
  lv_group_set_default(g);
  button_read_timer = lv_timer_create([](lv_timer_t *timer)
                                      {
  enterButton.tick();
  nextButton.tick();
  prevButtton.tick(); },
                                      5, NULL);
}

void routine(uint8_t timeout)
{
  static unsigned long last_update_time = 0;
  if (millis() - last_update_time >= timeout)
  {
    lv_task_handler();
    last_update_time = millis();
  }
}

// extern Display Screen_BSP;

static void changeScreen()
{
  // monitorController.model.speaker.beep();
  switch ((++currentScreen) % 2)
  // switch ((currentScreen) % 2)
  {
  case 0:
    bubblecontroller.onViewDisappear();   
    watchcontroller.onViewLoad();
    break;
  case 1:
    watchcontroller.onViewDisappear();
    bubblecontroller.onViewLoad();
    break;

  default:
    break;
  }
}

#endif